#include "Subsystems/BlockBehaviors/SubsystemFurnaceBlockBehavior.h"
#include "Subsystems/SubsystemBlockEntities.h"
#include "Subsystems/SubsystemTimeOfDay.h"

#include "Components/ComponentBlockEntity.h"
#include "Components/ComponentFurnace.h"

#include "Blocks/FurnaceBlock.h"
#include "Blocks/LitFurnaceBlock.h"

#include "GameSingleton.h"
#include "GameRegistry.hpp"
#include "Log.h"

#include "Network/PackageManager.h"
#include "Network/Packages/ComponentFurnacePackage.h"


namespace PocketSurvival
{
    SubsystemFurnaceBlockBehavior::SubsystemFurnaceBlockBehavior() 
    {
        m_handleBlocks.push_back(FurnaceBlock::Index());
        m_handleBlocks.push_back(LitFurnaceBlock::Index());
    }

    void SubsystemFurnaceBlockBehavior::onBlockAdded(int32_t value, int32_t oldValue, int32_t x, int32_t y, int32_t z)
    {
        if (Terrain::ExtractContents(oldValue) != FurnaceBlock::Index() && Terrain::ExtractContents(oldValue) != LitFurnaceBlock::Index())
        {
            Point3 point(x,y,z);
            m_subsystemBlockEntities->addBlockEntity("Furnace", point);
        }
    }
    
	void SubsystemFurnaceBlockBehavior::onBlockRemoved(int32_t value, int32_t newValue, int32_t x, int32_t y, int32_t z)
    {
        // 炉子和燃烧中的炉子替换时，实体不应该被移除
        if (Terrain::ExtractContents(newValue) != FurnaceBlock::Index() && Terrain::ExtractContents(newValue) != LitFurnaceBlock::Index())
        {
            std::lock_guard<std::recursive_mutex> lk(m_subsystemBlockEntities->blockEntitiesMutex);
            ComponentBlockEntity *blockEntity = m_subsystemBlockEntities->findBlockEntity(x, y, z);
            if(blockEntity != nullptr)
            {
                Vector3 position(x, y, z);
                position += 0.5f;
                ComponentFurnace *componentFurnace = GameSingleton::gameRegistry->get<ComponentFurnace*>(blockEntity->entity);
                componentFurnace->dropAllItems(position);
                m_subsystemBlockEntities->removeBlockEntity(blockEntity);
            }
        }
    }

    bool SubsystemFurnaceBlockBehavior::onInteract(const TerrainRaycastResult &raycastResult, ComponentMiner *componentMiner)
    {
        return false;
    }

    void SubsystemFurnaceBlockBehavior::update(float dt)
    {
        if (m_subsystemTimeOfDay->periodicGameTimeEvent(0.1, 0.0))
        {
            GameSingleton::packageManager->addSendPackageToQueue(std::make_shared<ComponentFurnacePackage>());
        }
    }

    static const std::string subsystemName = "FurnaceBlockBehavior";
    const std::string& SubsystemFurnaceBlockBehavior::getName() const
    {
        return subsystemName;
    }
    void SubsystemFurnaceBlockBehavior::load(const nlohmann::json &json)
    {
        m_subsystemBlockEntities = GameSingleton::singletonPtr->getSingleton<SubsystemBlockEntities>();
        m_subsystemTimeOfDay = GameSingleton::singletonPtr->getSingleton<SubsystemTimeOfDay>();
    }
    SubUpdateType SubsystemFurnaceBlockBehavior::getUpdateType()
    {
        return SubUpdateType::MultiThreadUpdate;
    }
}